#include <iostream>
#include <thread>
#include <atomic>
#include <string>
#include <functional>
#include <sys/socket.h>
#include <sys/un.h>
#include <unistd.h>
#include <cstring>
#include <cerrno>
#include <fcntl.h>

#include "app.hpp"
#include "unixsock.hpp"

using namespace wheels;
using namespace dm;

// 构造函数
unixSock::unixSock(const std::string& name) 
    : m_is_running__(false), m_sock_name__(name), m_sock_fd__(-1) 
{
    // 创建Unix域套接字
    m_sock_fd__ = socket(AF_UNIX, SOCK_STREAM, 0);
    if (m_sock_fd__ == -1) {
        throw std::runtime_error( std::string( "创建套接字失败: " ) + strerror(errno) );
    }
    
    // 设置套接字为非阻塞模式
    int flags = fcntl(m_sock_fd__, F_GETFL, 0);
    if (flags == -1) {
        close(m_sock_fd__);
        m_sock_fd__ = -1;
        throw std::runtime_error( std::string( "获取套接字标志失败: " ) + strerror(errno) );
    }
    
    if (fcntl(m_sock_fd__, F_SETFL, flags | O_NONBLOCK) == -1) {
        close(m_sock_fd__);
        m_sock_fd__ = -1;
        throw std::runtime_error( std::string( "设置套接字为非阻塞模式失败: " ) + strerror(errno) );
    }

    // 绑定套接字到指定路径
    struct sockaddr_un addr;
    memset(&addr, 0, sizeof(addr));
    addr.sun_family = AF_UNIX;
    strncpy(addr.sun_path, m_sock_name__.c_str(), sizeof(addr.sun_path) - 1);
    
    // 先删除可能已存在的socket文件
    unlink(m_sock_name__.c_str());
    
    if (bind(m_sock_fd__, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
        close(m_sock_fd__);
        m_sock_fd__ = -1;
        throw std::runtime_error( std::string( "绑定套接字失败: " ) + strerror(errno) );
    }
    
    // 开始监听
    if (listen(m_sock_fd__, 5) == -1) {
        
        close(m_sock_fd__);
        m_sock_fd__ = -1;
        throw std::runtime_error( std::string( "监听套接字失败: " ) + strerror(errno) );
    }
}

// 析构函数
unixSock::~unixSock() {
    // 确保线程停止
    start(false);
    
    // 关闭套接字
    if (m_sock_fd__ != -1) {
        close(m_sock_fd__);
        m_sock_fd__ = -1;
    }
    
    // 删除socket文件
    unlink(m_sock_name__.c_str());
}

// 启动或停止后台线程
bool unixSock::start(bool sw) {

    if( m_is_running__ == sw ){
        return true;
    }

    m_is_running__ = sw;
    if (sw) {
        // 启动后台线程
        m_thd__ = std::thread(&unixSock::backend__, this);
    } else {
        // 如果线程是可连接的，等待线程结束
        if (m_thd__.joinable()) {
            m_thd__.join();
        }
    }
    return true;
}

// 后台线程函数
void unixSock::backend__() {
    fd_set read_fds;
    struct timeval tv;
    int client_fd = -1;
    char buffer[4096];
    
    auto ptapp = app_t::get_shared();
    dispatch_t * dspt = ptapp->getDispatch();
    if( !dspt ){
        ERROR_MSG( "" );
        debug::printCallstack();
        return;
    }

    while (m_is_running__) {
        // 设置文件描述符集合
        FD_ZERO(&read_fds);
        FD_SET(m_sock_fd__, &read_fds);
        
        if (client_fd != -1) {
            FD_SET(client_fd, &read_fds);
        }
        
        // 设置超时时间
        tv.tv_sec = 1;
        tv.tv_usec = 0;
        
        // 等待套接字活动
        int max_fd = (client_fd > m_sock_fd__) ? client_fd : m_sock_fd__;
        int activity = select(max_fd + 1, &read_fds, NULL, NULL, &tv);
        
        if (activity < 0 && errno != EINTR) {
            ERROR_MSG( std::string( "Select 失败: " ) +  strerror(errno) );
            continue;
        }
        
        // 检查是否有新的连接
        if (FD_ISSET(m_sock_fd__, &read_fds)) {
            client_fd = accept(m_sock_fd__, NULL, NULL);
            if (client_fd == -1) {
                ERROR_MSG( std::string( "接受连接失败: " ) +  strerror(errno) );
            }
        }
        
        // 检查客户端是否有数据可读
        if (client_fd != -1 && FD_ISSET(client_fd, &read_fds)) {
            ssize_t bytes_read = read(client_fd, buffer, sizeof(buffer) - 1);
            
            if (bytes_read > 0) {
                buffer[bytes_read] = '\0';
                dspt->emit( emCmdType::DATA , std::string( buffer ) );
            } else if (bytes_read == 0) {
                close(client_fd);
                client_fd = -1;
            } else {
                // 读取错误
                if (errno != EAGAIN && errno != EWOULDBLOCK) {
                    ERROR_MSG( std::string(  "读取数据失败: " ) +  strerror(errno) );
                    close(client_fd);
                    client_fd = -1;
                }
            }
        }
        
        // 短暂休眠以减少CPU使用
        std::this_thread::sleep_for(std::chrono::milliseconds(10));
    }
    
    // 清理客户端连接
    if (client_fd != -1) {
        close(client_fd);
    }
}